package com.well.register.console.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.well.register.config.ClusterPropertiesConfig;
import com.well.register.console.aop.WellException;
import com.well.register.console.dao.ServerMapper;
import com.well.register.console.domain.ServerModel;
import com.well.register.console.model.server.QueryRegisterServerParam;
import com.well.register.console.model.server.ServerStatus;
import com.well.register.console.service.ServerService;
import com.well.register.data.DataCenter;
import com.well.register.eventAndlistener.ServerDownEvent;
import com.well.rpc.model.RegisterModel;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.well.register.console.model.server.ErrorInfo.SERVER_NOT_FOUND;

/**
 * <p>
 * server service impl
 * </p>
 *
 * @author weedo
 * @since 2022/8/10
 */
@Service
public class ServerServiceImpl extends ServiceImpl<ServerMapper, ServerModel>  implements ServerService {

    @Resource
    private ClusterPropertiesConfig config;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 获取登录用户注册的服务
     * @return
     * @param param
     */
    @Override
    public List<ServerModel> registerServerModel(QueryRegisterServerParam param) {
        QueryWrapper<ServerModel> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(param.getNamespace()))
            wrapper.eq("namespace", param.getNamespace());
        if (StringUtils.isNotBlank(param.getWellGroup()))
            wrapper.eq("well_group", param.getWellGroup());
        if (StringUtils.isNotBlank(param.getServername()))
            wrapper.eq("servername", param.getServername());
        if (StringUtils.isNotBlank(param.getServerIp()))
            wrapper.eq("server_ip", param.getServerIp());
        if (param.getRunType() != null)
            wrapper.eq("run_type", param.getRunType());
        if (param.getServerPort() != null)
            wrapper.eq("server_port", param.getServerPort());

        return this.baseMapper.selectList(wrapper);
    }

    /**
     *  根据条件查询
     * @param model
     * @return
     */
    @Override
    public ServerModel oneRegisterServer(RegisterModel model) {
        QueryWrapper<ServerModel> wrapper = new QueryWrapper<>();
        wrapper.eq("namespace", model.getNameSpace())
                .eq("well_group", model.getGroup())
                .eq("servername", model.getServerName())
                .eq("server_ip", model.getServerIp())
                .eq("server_port", model.getServerPort())
                .eq("accesskey", model.getAccessKey());
        return this.getOne(wrapper);
    }

    /**
     * 服务启动
     * @param registerModel
     * @return
     */
    @Override
    public boolean serverUp(RegisterModel registerModel) {
        ServerModel serverModel = oneRegisterServer(registerModel);
        Date date = new Date();
        if (serverModel == null) {
            serverModel = convertServerModel(registerModel);
            serverModel.setCreateTime(date);
        }
        serverModel.setUpdateTime(date);
        serverModel.setRunType(ServerStatus.UP.getCode());
        serverModel.setWellId(config.getId());
        serverModel.setRemoteAddress(registerModel.getSubThreadAddr());
        return this.saveOrUpdate(serverModel);
    }

    /**
     * 优雅下线
     * @param id
     */
    @Override
    public void serverDownGracefully(int id) throws WellException {
        ServerModel serverModel = this.getById(id);
        if (serverModel == null) {
            throw new WellException(SERVER_NOT_FOUND.getCode(), SERVER_NOT_FOUND.getMsg());
        }
        RegisterModel model = convertRegisterModel(serverModel);
        ChannelHandlerContext channelHandlerContext = DataCenter.getChannelHandlerContext(model);
        if (channelHandlerContext !=null && !channelHandlerContext.isRemoved()) {
            channelHandlerContext.close();
        }
    }

    private ServerModel convertServerModel(RegisterModel model) {
        ServerModel serverModel = new ServerModel();
        serverModel.setWellGroup(model.getGroup());
        serverModel.setNamespace(model.getNameSpace());
        serverModel.setServerIp(model.getServerIp());
        serverModel.setServerPort(model.getServerPort());
        serverModel.setServername(model.getServerName());
        serverModel.setAccesskey(model.getAccessKey());
        return serverModel;
    }

    private RegisterModel convertRegisterModel(ServerModel serverModel) {
        RegisterModel registerModel = new RegisterModel();
        registerModel.setNameSpace(serverModel.getNamespace());
        registerModel.setGroup(serverModel.getWellGroup());
        registerModel.setServerName(serverModel.getServername());
        registerModel.setServerIp(serverModel.getServerIp());
        registerModel.setServerPort(serverModel.getServerPort());
        registerModel.setSubThreadAddr(serverModel.getRemoteAddress());
        return registerModel;
    }

    @Override
    public void restoreRegisterServerState() {
        UpdateWrapper<ServerModel> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("well_id", config.getId())
                     .eq("run_type", ServerStatus.UP.getCode())
                     .set("run_type", ServerStatus.DOWN.getCode())
                     .set("update_time", new Date())
                     .set("remote_address", null);
        this.update(updateWrapper);
    }

    @Override
    public int countActivityServer(RegisterModel registerModel) {
        QueryWrapper<ServerModel> wrapper = new QueryWrapper<>();
        wrapper.eq("namespace", registerModel.getNameSpace())
                .eq("well_group", registerModel.getGroup())
                .eq("servername", registerModel.getServerName())
                .eq("well_id", config.getId())
                .eq("run_type", ServerStatus.UP.getCode());
        return this.count(wrapper);
    }

    @Override
    public boolean haveValidServer(String namespace, String group, String servername) {
        QueryWrapper<ServerModel> wrapper = new QueryWrapper<>();
        wrapper.eq("namespace", namespace)
                .eq("well_group", group)
                .eq("servername", servername)
                .eq("run_type", ServerStatus.UP.getCode());
        return this.count(wrapper) > 0;
    }

    /**
     * 服务下线
     * @param model
     * @return
     */
    @Override
    public boolean serverDown(RegisterModel model) {
        ServerModel serverModel = oneRegisterServer(model);
        if (serverModel == null) {
            return false;
        }
        serverModel.setUpdateTime(new Date());
        serverModel.setRunType(ServerStatus.DOWN.getCode());
        serverModel.setRemoteAddress(null);
        boolean update = this.updateById(serverModel);
        applicationEventPublisher.publishEvent(new ServerDownEvent(model));
        return update;
    }

}
